package domain.lexicalAnalyzerGenerator;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import domain.grammar.ExtendedGrammar;
import domain.grammar.ExtendedGrammarConflictException;
import domain.grammar.ExtendedProduction;
import domain.regularExpression.RegularExpressionElement;

public class FunctionSet {

	private String _grammar;
	private Set<Function> _functions;
	private Function _initialFunction;
	
	public static FunctionSet create(ExtendedGrammar extendedGrammar) throws InstructionException, ExtendedGrammarConflictException {
		Set<RegularExpressionElement> elemsInConflict = extendedGrammar.getElementsWithConflict();
		if(!elemsInConflict.isEmpty()){
			throw new ExtendedGrammarConflictException(elemsInConflict);
		}
		Instruction.currentExtendedGrammar = extendedGrammar;
		FunctionSet functionSet = new FunctionSet();
		functionSet._functions = new HashSet<Function>();
		functionSet._grammar = extendedGrammar.toString();
		
		Iterator<ExtendedProduction> itr = extendedGrammar.get_productions().get_productions().iterator();
		Function function;
		ExtendedProduction extendedProduction;
		while(itr.hasNext()) {
			extendedProduction = itr.next();
			function = Function.create(extendedProduction);
			functionSet._functions.add(function);
			
			if (extendedProduction.get_leftSide().equals(extendedGrammar.get_mainSymbol())){
				functionSet._initialFunction = function;
			}
		}
		
		return functionSet;
	}
	

	public String generateCode() 
	throws CodeGenerationException {
		String code = "";
		
		code += "package main;\n";
		code += "\n";
		code += "public class Main {\n";
		code += "	private static GrammarStringHelper grammarStringHelper;\n";
		code += "\n";
		code += "	public static void main(String[] args) {\n";
		code += "		CommandWindowInterface.startWindowInterface(" + transformToStringConstruction(_grammar) + ");\n";
		code += "	}\n";
		code += "\n";
		code += "	static void parse(String string)";
		code += "		throws ParseFailedException {\n";
		code += "		string = string + \"$\";\n";
		code += "		grammarStringHelper = new GrammarStringHelper(string);\n";
		code += "		" + this._initialFunction.getCall() + "\n";
		code += "		if (!grammarStringHelper.matchCurrentToken('$')){\n";
		code += "			System.out.println(\"El simbolo actual : \\n\" + grammarStringHelper.getCurrentTokenInfo() + \"\\n\"" + "\n";
		code += "			+\"no corresponde con el simbolo esperado:'$'\");\n";
		code += "			throw new ParseFailedException();\n";
		code += "		}\n";
		code += "		System.out.println(\"La cadena pertenece al lenguaje que define la gramatica\");\n";
		code += "	}\n";

		Iterator<Function> itr = this._functions.iterator();
		while(itr.hasNext()) {
			code += 	"\n";
			code +=  itr.next().generateCode() + "\n";
		}

		code += 		"}";

		return code;
	}
	
	private String transformToStringConstruction(String aString){
		String result = "\"";
		int i = 0;
		while(i<aString.length()){
			Character aChar = aString.charAt(i);
			if(aChar == 10){
				result += "\"";
				result += "\n";
				result +="+ \"";
			}else{
				result += aChar; 
			}
			i++;
		}
		result += "\"";
		return result;
	}
	
}